home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / phantz.arc / PHANT3.Z / PHANT3
Text File  |  1991-06-06  |  62KB  |  2,428 lines

  1.  
  2. : ---------CUT HERE---------
  3. : This is a shar archive.  Extract with sh, not csh.
  4. : The rest of this file will extract:
  5. :  interplayer.c gamesupport.c io.c
  6. echo x - interplayer.c
  7. sed 's/^X//' > interplayer.c << '!EOR!'
  8. X/*
  9. X * interplayer.c - player to player routines for Phantasia
  10. X */
  11. X
  12. X#include "include.h"
  13. X
  14. X/************************************************************************
  15. X/
  16. X/ FUNCTION NAME: checkbattle()
  17. X/
  18. X/ FUNCTION: check to see if current player should battle another
  19. X/
  20. X/ AUTHOR: E. A. Estes, 12/4/85
  21. X/
  22. X/ ARGUMENTS: none
  23. X/
  24. X/ RETURN VALUE: none
  25. X/
  26. X/ MODULES CALLED: battleplayer(), fread(), fseek()
  27. X/
  28. X/ GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
  29. X/
  30. X/ GLOBAL OUTPUTS: Users
  31. X/
  32. X/ DESCRIPTION:
  33. X/    Seach player file for a foe at the same coordinates as the
  34. X/    current player.
  35. X/    Also update user count.
  36. X/
  37. X/************************************************************************/
  38. X
  39. Xcheckbattle()
  40. X{
  41. Xlong    foeloc = 0L;        /* location in file of person to fight */
  42. X
  43. X    Users = 0;
  44. X    fseek(Playersfp, 0L, 0);
  45. X
  46. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  47. X    {
  48. X    if (Other.p_status != S_OFF
  49. X        && Other.p_status != S_NOTUSED
  50. X        && Other.p_status != S_HUNGUP
  51. X        && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
  52. X        /* player is on and not a cloaked valar */
  53. X        {
  54. X        ++Users;
  55. X
  56. X        if (Player.p_x == Other.p_x
  57. X        && Player.p_y == Other.p_y
  58. X        /* same coordinates */
  59. X        && foeloc != Fileloc
  60. X        /* not self */
  61. X        && Player.p_status == S_PLAYING
  62. X        && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
  63. X        /* both are playing */
  64. X        && Other.p_specialtype != SC_VALAR
  65. X        && Player.p_specialtype != SC_VALAR)
  66. X        /* neither is valar */
  67. X        {
  68. X        battleplayer(foeloc);
  69. X        return;
  70. X        }
  71. X        }
  72. X    foeloc += SZ_PLAYERSTRUCT;
  73. X    }
  74. X}
  75. X/* */
  76. X/************************************************************************
  77. X/
  78. X/ FUNCTION NAME: battleplayer()
  79. X/
  80. X/ FUNCTION: inter-terminal battle with another player
  81. X/
  82. X/ AUTHOR: E. A. Estes, 2/15/86
  83. X/
  84. X/ ARGUMENTS:
  85. X/    long foeplace - location in player file of person to battle
  86. X/
  87. X/ RETURN VALUE: none
  88. X/
  89. X/ MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(), 
  90. X/    displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(), 
  91. X/    myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(), 
  92. X/    getanswer(), wclrtoeol(), wclrtobot()
  93. X/
  94. X/ GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr, 
  95. X/    Fileloc, *Enemyname
  96. X/
  97. X/ GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
  98. X/
  99. X/ DESCRIPTION:
  100. X/    Inter-terminal battle is a very fragile and slightly klugy thing.
  101. X/    At any time, one player is master and the other is slave.
  102. X/    We pick who is master first by speed and level.  After that,
  103. X/    the slave waits for the master to relinquish its turn, and
  104. X/    the slave becomes master, and so on.
  105. X/
  106. X/    The items in the player structure which control the handshake are:
  107. X/        p_tampered:
  108. X/        master increments this to relinquish control
  109. X/        p_istat:
  110. X/        master sets this to specify particular action
  111. X/        p_1scratch:
  112. X/        set to total damage inflicted so far; changes to indicate action
  113. X/
  114. X/************************************************************************/
  115. X
  116. Xbattleplayer(foeplace)
  117. Xlong    foeplace;
  118. X{
  119. Xdouble    dtemp;        /* for temporary calculations */
  120. Xdouble    oldhits = 0.0;    /* previous damage inflicted by foe */
  121. Xregister int    loop;    /* for timing out */
  122. Xint    ch;        /* input */
  123. Xshort    oldtampered;    /* old value of foe's p_tampered */
  124. X
  125. X    Lines = 8;
  126. X    Luckout = FALSE;
  127. X    mvaddstr(4, 0, "Preparing for battle!\n");
  128. X    refresh();
  129. X
  130. X#ifdef SYS5
  131. X    flushinp();
  132. X#endif
  133. X
  134. X    /* set up variables, file, etc. */
  135. X    Player.p_status = S_INBATTLE;
  136. X    Shield = Player.p_energy;
  137. X
  138. X    /* if p_tampered is not 0, someone else may try to change it (king, etc.) */
  139. X    Player.p_tampered = oldtampered = 1;
  140. X    Player.p_1scratch = 0.0;
  141. X    Player.p_istat = I_OFF;
  142. X
  143. X    readrecord(&Other, foeplace);
  144. X    if (fabs(Player.p_level - Other.p_level) > 20.0)
  145. X    /* see if players are greatly mismatched */
  146. X    {
  147. X    dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
  148. X    if (dtemp < -0.5)
  149. X        /* foe outweighs this one */
  150. X        Player.p_speed *= 2.0;
  151. X    }
  152. X
  153. X    writerecord(&Player, Fileloc);        /* write out all our info */
  154. X
  155. X    if (Player.p_blindness)
  156. X    Enemyname = "someone";
  157. X    else
  158. X    Enemyname = Other.p_name;
  159. X
  160. X    mvprintw(6, 0, "You have encountered %s   Level: %.0f\n", Enemyname, Other.p_level);
  161. X    refresh();
  162. X
  163. X    for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
  164. X    /* wait for foe to respond */
  165. X    {
  166. X    readrecord(&Other, foeplace);
  167. X    sleep(1);
  168. X    }
  169. X
  170. X    if (Other.p_status != S_INBATTLE)
  171. X    /* foe did not respond */
  172. X    {
  173. X    mvprintw(5, 0, "%s is not responding.\n", Enemyname);
  174. X    goto LEAVE;
  175. X    }
  176. X    /* else, we are ready to battle */
  177. X
  178. X    move(4, 0);
  179. X    clrtoeol();
  180. X
  181. X    /*
  182. X     * determine who is first master
  183. X     * if neither player is faster, check level
  184. X     * if neither level is greater, battle is not allowed
  185. X     * (this should never happen, but we have to handle it)
  186. X     */
  187. X    if (Player.p_speed > Other.p_speed)
  188. X    Foestrikes = FALSE;
  189. X    else if (Other.p_speed > Player.p_speed)
  190. X    Foestrikes = TRUE;
  191. X    else if (Player.p_level > Other.p_level)
  192. X    Foestrikes = FALSE;
  193. X    else if (Other.p_level > Player.p_level)
  194. X    Foestrikes = TRUE;
  195. X    else
  196. X    /* no one is faster */
  197. X    {
  198. X    printw("You can't fight %s yet.", Enemyname);
  199. X    goto LEAVE;
  200. X    }
  201. X
  202. X    for (;;)
  203. X    {
  204. X    displaystats();
  205. X    readmessage();
  206. X    mvprintw(1, 26, "%20.0f", Shield);    /* overprint energy */
  207. X
  208. X    if (!Foestrikes)
  209. X        /* take action against foe */
  210. X        myturn();
  211. X    else
  212. X        /* wait for foe to take action */
  213. X        {
  214. X        mvaddstr(4, 0, "Waiting...\n");
  215. X        clrtoeol();
  216. X        refresh();
  217. X
  218. X        for (loop = 0; loop < 20; ++loop)
  219. X        /* wait for foe to act */
  220. X        {
  221. X        readrecord(&Other, foeplace);
  222. X        if (Other.p_1scratch != oldhits)
  223. X            /* p_1scratch changes to indicate action */
  224. X            break;
  225. X        else
  226. X            /* wait and try again */
  227. X            {
  228. X            sleep(1);
  229. X            addch('.');
  230. X            refresh();
  231. X            }
  232. X        }
  233. X
  234. X        if (Other.p_1scratch == oldhits)
  235. X        {
  236. X        /* timeout */
  237. X        mvaddstr(22, 0, "Timeout: waiting for response.  Do you want to wait ? ");
  238. X        ch = getanswer("NY", FALSE);
  239. X        move(22, 0);
  240. X        clrtobot();
  241. X        if (ch == 'Y')
  242. X            continue;
  243. X        else
  244. X            break;
  245. X        }
  246. X        else
  247. X        /* foe took action */
  248. X        {
  249. X        switch (Other.p_istat)
  250. X            {
  251. X            case I_RAN:        /* foe ran away */
  252. X            mvprintw(Lines++, 0, "%s ran away!", Enemyname);
  253. X            break;
  254. X
  255. X            case I_STUCK:    /* foe tried to run, but couldn't */
  256. X            mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
  257. X            break;
  258. X
  259. X            case I_BLEWIT:    /* foe tried to luckout, but didn't */
  260. X            mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
  261. X            break;
  262. X
  263. X            default:
  264. X            dtemp = Other.p_1scratch - oldhits;
  265. X            mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
  266. X            Shield -= dtemp;
  267. X            break;
  268. X            }
  269. X
  270. X        oldhits = Other.p_1scratch;    /* keep track of old hits */
  271. X
  272. X        if (Other.p_tampered != oldtampered)
  273. X            /* p_tampered changes to relinquish turn */
  274. X            {
  275. X            oldtampered = Other.p_tampered;
  276. X            Foestrikes = FALSE;
  277. X            }
  278. X        }
  279. X        }
  280. X
  281. X    /* decide what happens next */
  282. X    refresh();
  283. X    if (Lines > LINES - 2)
  284. X        {
  285. X        more(Lines);
  286. X        move(Lines = 8, 0);
  287. X        clrtobot();
  288. X        }
  289. X
  290. X    if (Other.p_istat == I_KILLED || Shield < 0.0)
  291. X        /* we died */
  292. X        {
  293. X        Shield = -2.0;        /* insure this value is negative */
  294. X        break;
  295. X        }
  296. X
  297. X    if (Player.p_istat == I_KILLED)
  298. X        /* we killed foe; award treasre */
  299. X        {
  300. X        mvprintw(Lines++, 0, "You killed %s!", Enemyname);
  301. X        Player.p_experience += Other.p_experience;
  302. X        Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
  303. X        Player.p_amulets += Other.p_amulets;
  304. X        Player.p_charms += Other.p_charms;
  305. X        collecttaxes(Other.p_gold, Other.p_gems);
  306. X        Player.p_sword = MAX(Player.p_sword, Other.p_sword);
  307. X        Player.p_shield = MAX(Player.p_shield, Other.p_shield);
  308. X        Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
  309. X        if (Other.p_virgin && !Player.p_virgin)
  310. X        {
  311. X        mvaddstr(Lines++, 0, "You have rescued a virgin.  Will you be honorable ? ");
  312. X        if ((ch = getanswer("YN", FALSE)) == 'Y')
  313. X            Player.p_virgin = TRUE;
  314. X        else
  315. X            {
  316. X            ++Player.p_sin;
  317. X            Player.p_experience += 8000.0;
  318. X            }
  319. X        }
  320. X        sleep(3);             /* give other person time to die */
  321. X        break;
  322. X        }
  323. X    else if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
  324. X        /* either player ran away */
  325. X        break;
  326. X    }
  327. X
  328. XLEAVE:
  329. X    /* clean up things and leave */
  330. X    writerecord(&Player, Fileloc);    /* update a final time */
  331. X    altercoordinates(0.0, 0.0, A_NEAR);    /* move away from battle site */
  332. X    Player.p_energy = Shield;        /* set energy to actual value */
  333. X    Player.p_tampered = T_OFF;        /* clear p_tampered */
  334. X
  335. X    more(Lines);            /* pause */
  336. X
  337. X    move(4, 0);
  338. X    clrtobot();                /* clear bottom area of screen */
  339. X
  340. X    if (Player.p_energy < 0.0)
  341. X    /* we are dead */
  342. X    death("Interterminal battle");
  343. X}
  344. X/* */
  345. X/************************************************************************
  346. X/
  347. X/ FUNCTION NAME: myturn()
  348. X/
  349. X/ FUNCTION: process players action against foe in battle
  350. X/
  351. X/ AUTHOR: E. A. Estes, 2/7/86
  352. X/
  353. X/ ARGUMENTS: none
  354. X/
  355. X/ RETURN VALUE: none
  356. X/
  357. X/ MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), random(), 
  358. X/    waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot()
  359. X/
  360. X/ GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout, 
  361. X/    *Enemyname
  362. X/
  363. X/ GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
  364. X/
  365. X/ DESCRIPTION:
  366. X/    Take action action against foe, and decide who is master
  367. X/    for next iteration.
  368. X/
  369. X/************************************************************************/
  370. X
  371. Xmyturn()
  372. X{
  373. Xdouble    dtemp;        /* for temporary calculations */
  374. Xint    ch;        /* input */
  375. X
  376. X    mvaddstr(7, 0, "1:Fight  2:Run Away!  3:Power Blast  ");
  377. X    if (Luckout)
  378. X    clrtoeol();
  379. X    else
  380. X    addstr("4:Luckout  ");
  381. X
  382. X    ch = inputoption();
  383. X    move(Lines = 8, 0);
  384. X    clrtobot();
  385. X
  386. X    switch (ch)
  387. X    {
  388. X    default:    /* fight */
  389. X        dtemp = ROLL(2.0, Player.p_might);
  390. XHIT:        
  391. X        mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
  392. X        Player.p_sin += 0.5;
  393. X        Player.p_1scratch += dtemp;
  394. X        Player.p_istat = I_OFF;
  395. X        break;
  396. X
  397. X    case '2':    /* run away */
  398. X        Player.p_1scratch -= 1.0;    /* change this to indicate action */
  399. X        if (random() > 0.25)
  400. X        {
  401. X        mvaddstr(Lines++, 0, "You got away!");
  402. X        Player.p_istat = I_RAN;
  403. X        }
  404. X        else
  405. X        {
  406. X        mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
  407. X        Player.p_istat = I_STUCK;
  408. X        }
  409. X        break;
  410. X
  411. X    case '3':    /* power blast */
  412. X        dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
  413. X        Player.p_mana -= dtemp;
  414. X        dtemp *= (random() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
  415. X        mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
  416. X        goto HIT;
  417. X
  418. X    case '4':    /* luckout */
  419. X        if (Luckout || random() > 0.1)
  420. X        {
  421. X        if (Luckout)
  422. X            mvaddstr(Lines++, 0, "You already tried that!");
  423. X        else
  424. X            {
  425. X            mvaddstr(Lines++, 0, "Not this time . . .");
  426. X            Luckout = TRUE;
  427. X            }
  428. X
  429. X        Player.p_1scratch -= 1.0;
  430. X        Player.p_istat = I_BLEWIT;
  431. X        }
  432. X        else
  433. X        {
  434. X        mvaddstr(Lines++, 0, "You just lucked out!");
  435. X        Player.p_1scratch = Other.p_energy * 1.1;
  436. X        }
  437. X        break;
  438. X    }
  439. X
  440. X    refresh();
  441. X    Player.p_1scratch = floor(Player.p_1scratch);    /* clean up any mess */
  442. X
  443. X    if (Player.p_1scratch > Other.p_energy)
  444. X    Player.p_istat = I_KILLED;
  445. X    else if (random() * Player.p_speed < random() * Other.p_speed)
  446. X    /* relinquish control */
  447. X    {
  448. X    ++Player.p_tampered;
  449. X    Foestrikes = TRUE;
  450. X    }
  451. X
  452. X    writerecord(&Player, Fileloc);            /* let foe know what we did */
  453. X}
  454. X/* */
  455. X/************************************************************************
  456. X/
  457. X/ FUNCTION NAME: checktampered()
  458. X/
  459. X/ FUNCTION: check if current player has been tampered with
  460. X/
  461. X/ AUTHOR: E. A. Estes, 12/4/85
  462. X/
  463. X/ ARGUMENTS: none
  464. X/
  465. X/ RETURN VALUE: none
  466. X/
  467. X/ MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid()
  468. X/
  469. X/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
  470. X/
  471. X/ GLOBAL OUTPUTS: Enrgyvoid
  472. X/
  473. X/ DESCRIPTION:
  474. X/    Check for energy voids, holy grail, and tampering by other
  475. X/    players.
  476. X/
  477. X/************************************************************************/
  478. X
  479. Xchecktampered()
  480. X{
  481. Xlong    loc = 0L;        /* location in energy void file */
  482. X
  483. X    /* first check for energy voids */
  484. X    fseek(Energyvoidfp, 0L, 0);
  485. X    while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
  486. X    if (Enrgyvoid.ev_active
  487. X        && Enrgyvoid.ev_x == Player.p_x
  488. X        && Enrgyvoid.ev_y == Player.p_y)
  489. X        /* sitting on one */
  490. X        {
  491. X        if (loc > 0L)
  492. X        /* not the holy grail; inactivate energy void */
  493. X        {
  494. X        Enrgyvoid.ev_active = FALSE;
  495. X        writevoid(&Enrgyvoid, loc);
  496. X        tampered(T_NRGVOID, 0.0, 0.0);
  497. X        }
  498. X        else if (Player.p_status != S_CLOAKED)
  499. X        /* holy grail */
  500. X        tampered(T_GRAIL, 0.0, 0.0);
  501. X        break;
  502. X        }
  503. X    else
  504. X        loc += SZ_VOIDSTRUCT;
  505. X
  506. X    /* now check for other things */
  507. X    readrecord(&Other, Fileloc);
  508. X    if (Other.p_tampered != T_OFF)
  509. X    tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
  510. X}
  511. X/* */
  512. X/************************************************************************
  513. X/
  514. X/ FUNCTION NAME: tampered()
  515. X/
  516. X/ FUNCTION: take care of tampering by other players
  517. X/
  518. X/ AUTHOR: E. A. Estes, 12/4/85
  519. X/
  520. X/ ARGUMENTS:
  521. X/    int what - what type of tampering
  522. X/    double arg1, arg2 - rest of tampering info
  523. X/
  524. X/ RETURN VALUE: none
  525. X/
  526. X/ MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(), 
  527. X/    floor(), wmove(), waddch(), random(), printw(), altercoordinates(), 
  528. X/    waddstr(), wrefresh(), encounter(), writevoid()
  529. X/
  530. X/ GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
  531. X/
  532. X/ GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
  533. X/
  534. X/ DESCRIPTION:
  535. X/    Take care of energy voids, holy grail, decree and intervention
  536. X/    action on current player.
  537. X/
  538. X/************************************************************************/
  539. X
  540. Xtampered(what, arg1, arg2)
  541. Xint    what;
  542. Xdouble    arg1;
  543. Xdouble    arg2;
  544. X{
  545. Xlong    loc;            /* location in file of other players */
  546. X
  547. X    Changed = TRUE;
  548. X    move(4,0);
  549. X
  550. X    Player.p_tampered = T_OFF;    /* no longer tampered with */
  551. X
  552. X    switch (what)
  553. X    {
  554. X    case T_NRGVOID:
  555. X        addstr("You've hit an energy void !\n");
  556. X        Player.p_mana /= 3.0;
  557. X        Player.p_energy /= 2.0;
  558. X        Player.p_gold = floor(Player.p_gold/1.25) + 0.1;
  559. X        altercoordinates(0.0, 0.0, A_NEAR);
  560. X        break;
  561. X
  562. X    case T_TRANSPORT:
  563. X        addstr("The king transported you !  ");
  564. X        if (Player.p_charms > 0)
  565. X        {
  566. X        addstr("But your charm save you. . .\n");
  567. X        --Player.p_charms;
  568. X        }
  569. X        else
  570. X        {
  571. X        altercoordinates(0.0, 0.0, A_FAR);
  572. X        addch('\n');
  573. X        }
  574. X        break;
  575. X
  576. X    case T_BESTOW:
  577. X        printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
  578. X        Player.p_gold += arg1;
  579. X        break;
  580. X
  581. X    case T_CURSED:
  582. X        addstr("You've been cursed !  ");
  583. X        if (Player.p_blessing)
  584. X        {
  585. X        addstr("But your blessing saved you. . .\n");
  586. X        Player.p_blessing = FALSE;
  587. X        }
  588. X        else
  589. X        {
  590. X        addch('\n');
  591. X        Player.p_poison += 2.0;
  592. X        Player.p_energy = 10.0;
  593. X        Player.p_maxenergy  *= 0.95;
  594. X        Player.p_status = S_PLAYING;    /* no longer cloaked */
  595. X        }
  596. X        break;
  597. X
  598. X    case T_VAPORIZED:
  599. X        addstr("You have been vaporized!\n");
  600. X        more(7);
  601. X        death("Vaporization");
  602. X        break;
  603. X
  604. X    case T_MONSTER:
  605. X        addstr("The Valar zapped you with a monster!\n");
  606. X        more(7);
  607. X        encounter((int) arg1);
  608. X        return;
  609. X
  610. X    case T_BLESSED:
  611. X        addstr("The Valar has blessed you!\n");
  612. X        Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
  613. X        Player.p_mana += 500.0;
  614. X        Player.p_strength += 0.5;
  615. X        Player.p_brains += 0.5;
  616. X        Player.p_magiclvl += 0.5;
  617. X        Player.p_poison = MIN(0.5, Player.p_poison);
  618. X        break;
  619. X
  620. X    case T_RELOCATE:
  621. X        addstr("You've been relocated. . .\n");
  622. X        altercoordinates(arg1, arg2, A_FORCED);
  623. X        break;
  624. X
  625. X    case T_HEAL:
  626. X        addstr("You've been healed!\n");
  627. X        Player.p_poison -=  0.25;
  628. X        Player.p_energy = Player.p_maxenergy + Player.p_shield;
  629. X        break;
  630. X
  631. X    case T_EXVALAR:
  632. X        addstr("You are no longer Valar!\n");
  633. X        Player.p_specialtype = SC_COUNCIL;
  634. X        break;
  635. X
  636. X    case T_GRAIL:
  637. X        addstr("You have found The Holy Grail!!\n");
  638. X        if (Player.p_specialtype < SC_COUNCIL)
  639. X        /* must be council of wise to behold grail */
  640. X        {
  641. X        addstr("However, you are not experienced enough to behold it.\n");
  642. X        Player.p_sin *= Player.p_sin;
  643. X        Player.p_mana +=  1000;
  644. X        }
  645. X        else if (Player.p_specialtype == SC_VALAR
  646. X        || Player.p_specialtype == SC_EXVALAR)
  647. X        {
  648. X        addstr("You have made it to the position of Valar once already.\n");
  649. X        addstr("The Grail is of no more use to you now.\n");
  650. X        }
  651. X        else
  652. X        {
  653. X        addstr("It is now time to see if you are worthy to behold it. . .\n");
  654. X        refresh();
  655. X        sleep(4);
  656. X
  657. X        if (random() / 2.0 < Player.p_sin)
  658. X            {
  659. X            addstr("You have failed!\n");
  660. X            Player.p_strength =
  661. X            Player.p_mana =
  662. X            Player.p_energy =
  663. X            Player.p_maxenergy =
  664. X            Player.p_magiclvl = 
  665. X            Player.p_brains =
  666. X            Player.p_experience =
  667. X            Player.p_quickness = 1.0;
  668. X
  669. X            altercoordinates(1.0, 1.0, A_FORCED);
  670. X            Player.p_level = 0.0;
  671. X            }
  672. X        else
  673. X            {
  674. X            addstr("You made to position of Valar!\n");
  675. X            Player.p_specialtype = SC_VALAR;
  676. X            Player.p_lives = 5;
  677. X            fseek(Playersfp, 0L, 0);
  678. X            loc = 0L;
  679. X            while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  680. X            /* search for existing valar */
  681. X            if (Other.p_specialtype == SC_VALAR
  682. X                && Other.p_status != S_NOTUSED)
  683. X                /* found old valar */
  684. X                {
  685. X                Other.p_tampered = T_EXVALAR;
  686. X                writerecord(&Other, loc);
  687. X                break;
  688. X                }
  689. X            else
  690. X                loc += SZ_PLAYERSTRUCT;
  691. X            }
  692. X        }
  693. X
  694. X        /* move grail to new location */
  695. X        Enrgyvoid.ev_active = TRUE;
  696. X        Enrgyvoid.ev_x = ROLL(-1e6, 2e6);
  697. X        Enrgyvoid.ev_y = ROLL(-1e6, 2e6);
  698. X        writevoid(&Enrgyvoid, 0L);
  699. X        break;
  700. X    }
  701. X    refresh();
  702. X    sleep(2);
  703. X}
  704. X/* */
  705. X/************************************************************************
  706. X/
  707. X/ FUNCTION NAME: userlist()
  708. X/
  709. X/ FUNCTION: print list of players and locations
  710. X/
  711. X/ AUTHOR: E. A. Estes, 2/28/86
  712. X/
  713. X/ ARGUMENTS:
  714. X/    bool ingameflag - set if called while playing
  715. X/
  716. X/ RETURN VALUE: none
  717. X/
  718. X/ MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(), 
  719. X/    floor(), wmove(), printw(), waddstr(), distance(), wrefresh(), 
  720. X/    descrtype(), wclrtobot()
  721. X/
  722. X/ GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
  723. X/
  724. X/ GLOBAL OUTPUTS: none
  725. X/
  726. X/ DESCRIPTION:
  727. X/    We can only see the coordinate of those closer to the origin
  728. X/    from us.
  729. X/    Kings and council of the wise can see and can be seen by everyone.
  730. X/    Palantirs are good for seeing everyone; and the valar can use
  731. X/    one to see through a 'cloak' spell.
  732. X/    The valar has no coordinates, and is completely invisible if
  733. X/    cloaked.
  734. X/
  735. X/************************************************************************/
  736. X
  737. Xuserlist(ingameflag)
  738. Xbool    ingameflag;
  739. X{
  740. Xregister int    numusers = 0;    /* number of users on file */
  741. X
  742. X    if (ingameflag && Player.p_blindness)
  743. X    {
  744. X    mvaddstr(8, 0, "You cannot see anyone.\n");
  745. X    return;
  746. X    }
  747. X
  748. X    fseek(Playersfp, 0L, 0);
  749. X    mvaddstr(8, 0,
  750. X    "Name                         X         Y    Lvl Type Login    Status\n");
  751. X
  752. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  753. X    {
  754. X    if (Other.p_status == S_NOTUSED
  755. X        /* record is unused */
  756. X        || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
  757. X        /* cloaked valar */
  758. X        {
  759. X        if (!Wizard)
  760. X        /* wizard can see everything on file */
  761. X        continue;
  762. X        }
  763. X
  764. X        ++numusers;
  765. X
  766. X        if (ingameflag &&
  767. X        /* must be playing for the rest of these conditions */
  768. X        (Player.p_specialtype >= SC_KING
  769. X        /* kings and higher can see others */
  770. X        || Other.p_specialtype >= SC_KING
  771. X        /* kings and higher can be seen by others */
  772. X        || Circle >= CIRCLE(Other.p_x, Other.p_y)
  773. X        /* those nearer the origin can be seen */
  774. X        || Player.p_palantir)
  775. X        /* palantir enables one to see others */
  776. X        && (Other.p_status != S_CLOAKED 
  777. X            || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
  778. X        /* not cloaked; valar can see through cloak with a palantir */
  779. X        && Other.p_specialtype != SC_VALAR)
  780. X        /* not a valar */
  781. X        /* coordinates should be printed */
  782. X        printw("%-20s  %8.0f  %8.0f ",
  783. X            Other.p_name, Other.p_x, Other.p_y);
  784. X        else
  785. X        /* cannot see player's coordinates */
  786. X        printw("%-20s %19.19s ",
  787. X            Other.p_name, descrlocation(&Other, TRUE));
  788. X    
  789. X    printw("%6.0f %s  %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
  790. X        Other.p_login, descrstatus(&Other));
  791. X
  792. X    if ((numusers % (LINES - 10)) == 0)
  793. X        {
  794. X        more(LINES - 1);
  795. X        move(9, 0);
  796. X        clrtobot();
  797. X        }
  798. X    }
  799. X
  800. X    printw("Total players on file = %d\n", numusers);
  801. X    refresh();
  802. X}
  803. X/* */
  804. X/************************************************************************
  805. X/
  806. X/ FUNCTION NAME: throneroom()
  807. X/
  808. X/ FUNCTION: king stuff upon entering throne
  809. X/
  810. X/ AUTHOR: E. A. Estes, 12/16/85
  811. X/
  812. X/ ARGUMENTS: none
  813. X/
  814. X/ RETURN VALUE: none
  815. X/
  816. X/ MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(), 
  817. X/    fwrite(), altercoordinates(), waddstr(), fprintf()
  818. X/
  819. X/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr, Voidfile[], 
  820. X/    Messfile[], Enrgyvoid, *Playersfp
  821. X/
  822. X/ GLOBAL OUTPUTS: Other, Player, Changed
  823. X/
  824. X/ DESCRIPTION:
  825. X/    If player is not already king, make him/her so if the old king
  826. X/    is not playing.
  827. X/    Clear energy voids with new king.
  828. X/    Print 'decree' prompt.
  829. X/
  830. X/************************************************************************/
  831. X
  832. Xthroneroom()
  833. X{
  834. XFILE    *fp;            /* to clear energy voids */
  835. Xlong    loc = 0L;        /* location of old king in player file */
  836. X
  837. X    if (Player.p_specialtype < SC_KING)
  838. X    /* not already king -- assumes crown */
  839. X    {
  840. X    fseek(Playersfp, 0L, 0);
  841. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  842. X        if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
  843. X        /* found old king */
  844. X        {
  845. X        if (Other.p_status != S_OFF)
  846. X            /* old king is playing */
  847. X            {
  848. X            mvaddstr( 4, 0, "The king is playing, so you cannot steal his throne\n");
  849. X            altercoordinates(0.0, 0.0, A_NEAR);
  850. X            move(6, 0);
  851. X            return;
  852. X            }
  853. X        else
  854. X            /* old king is not playing - remove him/her */
  855. X            {
  856. X            Other.p_specialtype = SC_NONE;
  857. X            if (Other.p_crowns)
  858. X            --Other.p_crowns;
  859. X            writerecord(&Other, loc);
  860. X            break;
  861. X            }
  862. X        }
  863. X        else
  864. X        loc += SZ_PLAYERSTRUCT;
  865. X
  866. X    /* make player new king */
  867. X    Changed = TRUE;
  868. X    Player.p_specialtype = SC_KING;
  869. X    mvaddstr(4, 0, "You have become king!\n");
  870. X
  871. X    /* let everyone else know */
  872. X    fp = fopen(Messfile, "w");
  873. X    fprintf(fp, "All hail the new king!");
  874. X    fclose(fp);
  875. X
  876. X    /* clear all energy voids; retain location of holy grail */
  877. X    fseek(Energyvoidfp, 0L, 0);
  878. X    fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
  879. X    fp = fopen(Voidfile, "w");
  880. X    fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
  881. X    fclose(fp);
  882. X    }
  883. X
  884. X    mvaddstr(6, 0, "0:Decree  ");
  885. X}
  886. X/* */
  887. X/************************************************************************
  888. X/
  889. X/ FUNCTION NAME: dotampered()
  890. X/
  891. X/ FUNCTION: king and valar special options
  892. X/
  893. X/ AUTHOR: E. A. Estes, 2/28/86
  894. X/
  895. X/ ARGUMENTS: none
  896. X/
  897. X/ RETURN VALUE: none
  898. X/
  899. X/ MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(), 
  900. X/    floor(), wmove(), random(), fclose(), fwrite(), sscanf(), strcmp(), 
  901. X/    infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(), 
  902. X/    allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid()
  903. X/
  904. X/ GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr, 
  905. X/    Databuf[], Goldfile[], Enrgyvoid
  906. X/
  907. X/ GLOBAL OUTPUTS: Other, Player, Enrgyvoid
  908. X/
  909. X/ DESCRIPTION:
  910. X/    Tamper with other players.  Handle king/valar specific options.
  911. X/
  912. X/************************************************************************/
  913. X
  914. Xdotampered()
  915. X{
  916. Xshort    tamper;            /* value for tampering with other players */
  917. Xchar    *option;            /* pointer to option description */
  918. Xdouble    temp1 = 0.0, temp2 = 0.0;    /* other tampering values */
  919. Xint    ch;                /* input */
  920. Xlong    loc;                /* location in energy void file */
  921. XFILE    *fp;                /* for opening gold file */
  922. X
  923. X    move(6, 0);
  924. X    clrtoeol();
  925. X    if (Player.p_specialtype < SC_COUNCIL && !Wizard)
  926. X    /* king options */
  927. X    {
  928. X    addstr("1:Transport  2:Curse  3:Energy Void  4:Bestow  5:Collect Taxes  ");
  929. X
  930. X    ch = getanswer(" ", TRUE);
  931. X    move(6, 0);
  932. X    clrtoeol();
  933. X    move(4, 0);
  934. X    switch (ch)
  935. X        {
  936. X        case '1':    /* transport someone */
  937. X        tamper = T_TRANSPORT;
  938. X        option = "transport";
  939. X        break;
  940. X
  941. X        case '2':    /* curse another */
  942. X        tamper = T_CURSED;
  943. X        option = "curse";
  944. X        break;
  945. X
  946. X        case '3':    /* create energy void */
  947. X        if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT)
  948. X            /* can only have 20 void active at once */
  949. X            mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
  950. X        else
  951. X            {
  952. X            addstr("Enter the X Y coordinates of void ? ");
  953. X            getstring(Databuf, SZ_DATABUF);
  954. X            sscanf(Databuf, "%F %F", &temp1, &temp2);
  955. X            Enrgyvoid.ev_x = floor(temp1);
  956. X            Enrgyvoid.ev_y = floor(temp2);
  957. X            Enrgyvoid.ev_active = TRUE;
  958. X            writevoid(&Enrgyvoid, loc);
  959. X            mvaddstr(5, 0, "It is done.\n");
  960. X            }
  961. X        return;
  962. X
  963. X        case '4':    /* bestow gold to subject */
  964. X        tamper = T_BESTOW;
  965. X        addstr("How much gold to bestow ? ");
  966. X        temp1 = infloat();
  967. X        if (temp1 > Player.p_gold || temp1 < 0)
  968. X            {
  969. X            mvaddstr(5, 0, "You don't have that !\n");
  970. X            return;
  971. X            }
  972. X
  973. X        Player.p_gold -= floor(temp1);
  974. X        option = "give gold to";
  975. X        break;
  976. X
  977. X        case '5':    /* collect accumulated taxes */
  978. X        if ((fp = fopen(Goldfile, "r+")) != NULL)
  979. X            /* collect taxes */
  980. X            {
  981. X            fread((char *) &temp1, sizeof(double), 1, fp);
  982. X            fseek(fp, 0L, 0);
  983. X            /* clear out value */
  984. X            temp2 = 0.0;
  985. X            fwrite((char *) &temp2, sizeof(double), 1, fp);
  986. X            fclose(fp);
  987. X            }
  988. X
  989. X        mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
  990. X        Player.p_gold += floor(temp1);
  991. X        return;
  992. X
  993. X        default:
  994. X        return;
  995. X        }
  996. X    /* end of king options */
  997. X    }
  998. X    else
  999. X    /* council of wise, valar, wizard options */
  1000. X    {
  1001. X    addstr("1:Heal  ");
  1002. X    if (Player.p_palantir || Wizard)
  1003. X        addstr("2:Seek Grail  ");
  1004. X    if (Player.p_specialtype == SC_VALAR || Wizard)
  1005. X        addstr("3:Throw Monster  4:Relocate  5:Bless  ");
  1006. X    if (Wizard)
  1007. X        addstr("6:Vaporize  ");
  1008. X
  1009. X    ch = getanswer(" ", TRUE);
  1010. X    if (!Wizard)
  1011. X        {
  1012. X        if (ch > '2' && Player.p_specialtype != SC_VALAR)
  1013. X        {
  1014. X        ILLCMD();
  1015. X        return;
  1016. X        }
  1017. X
  1018. X        if (Player.p_mana < MM_INTERVENE)
  1019. X        {
  1020. X        mvaddstr(5, 0, "No mana left.\n");
  1021. X        return;
  1022. X        }
  1023. X        else
  1024. X        Player.p_mana -= MM_INTERVENE;
  1025. X        }
  1026. X
  1027. X    switch (ch)
  1028. X        {
  1029. X        case '1':    /* heal another */
  1030. X        tamper = T_HEAL;
  1031. X        option = "heal";
  1032. X        break;
  1033. X
  1034. X        case '2':    /* seek grail */
  1035. X        if (Player.p_palantir)
  1036. X            /* need a palantir to seek */
  1037. X            {
  1038. X            fseek(Energyvoidfp, 0L, 0);
  1039. X            fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
  1040. X            temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
  1041. X            temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0);    /* add some error */
  1042. X            mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
  1043. X            }
  1044. X        else
  1045. X            /* no palantir */
  1046. X            mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
  1047. X        return;
  1048. X
  1049. X        case '3':    /* lob monster at someone */
  1050. X        mvaddstr(4, 0, "Which monster [0-99] ? ");
  1051. X        temp1 = infloat();
  1052. X        temp1 = MAX(0.0, MIN(99.0, temp1));
  1053. X        tamper = T_MONSTER;
  1054. X        option = "throw a monster at";
  1055. X        break;
  1056. X
  1057. X        case '4':    /* move another player */
  1058. X        mvaddstr(4, 0, "New X Y coordinates ? ");
  1059. X        getstring(Databuf, SZ_DATABUF);
  1060. X        sscanf(Databuf, "%F %F", &temp1, &temp2);
  1061. X        tamper = T_RELOCATE;
  1062. X        option = "relocate";
  1063. X        break;
  1064. X
  1065. X        case '5':    /* bless a player */
  1066. X        tamper = T_BLESSED;
  1067. X        option = "bless";
  1068. X        break;
  1069. X
  1070. X        case '6':    /* kill off a player */
  1071. X        if (Wizard)
  1072. X            {
  1073. X            tamper = T_VAPORIZED;
  1074. X            option = "vaporize";
  1075. X            break;
  1076. X            }
  1077. X        else
  1078. X            return;
  1079. X
  1080. X        default:
  1081. X        return;
  1082. X        }
  1083. X
  1084. X    if (!Wizard)
  1085. X        Player.p_age += N_AGE;        /* penalty for using this stuff */
  1086. X    /* end of valar, etc. options */
  1087. X    }
  1088. X
  1089. X    for (;;)
  1090. X    /* prompt for player to affect */
  1091. X    {
  1092. X    mvprintw(4, 0, "Who do you want to %s ? ", option);
  1093. X    getstring(Databuf, SZ_DATABUF);
  1094. X    truncstring(Databuf);
  1095. X
  1096. X    if (Databuf[0] == '\0')
  1097. X        userlist(TRUE);
  1098. X    else
  1099. X        break;
  1100. X    }
  1101. X
  1102. X    if (strcmp(Player.p_name, Databuf) != 0)
  1103. X    /* name other than self */
  1104. X    {
  1105. X    if ((loc = findname(Databuf, &Other)) >= 0L)
  1106. X        {
  1107. X        if (Other.p_tampered != T_OFF)
  1108. X        {
  1109. X        mvaddstr(5, 0, "That person has something pending already.\n");
  1110. X        return;
  1111. X        }
  1112. X        else
  1113. X        {
  1114. X        if (tamper == T_RELOCATE
  1115. X            && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
  1116. X            && !Wizard)
  1117. X            mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
  1118. X        else
  1119. X            {
  1120. X            Other.p_tampered = tamper;
  1121. X            Other.p_1scratch = floor(temp1);
  1122. X            Other.p_2scratch = floor(temp2);
  1123. X            writerecord(&Other, loc);
  1124. X            mvaddstr(5, 0, "It is done.\n");
  1125. X            }
  1126. X        return;
  1127. X        }
  1128. X        }
  1129. X    else
  1130. X        /* player not found */
  1131. X        mvaddstr(5, 0, "There is no one by that name.\n");
  1132. X    }
  1133. X    else
  1134. X    /* self */
  1135. X    mvaddstr(5, 0, "You may not do it to yourself!\n");
  1136. X}
  1137. X/* */
  1138. X/************************************************************************
  1139. X/
  1140. X/ FUNCTION NAME: writevoid()
  1141. X/
  1142. X/ FUNCTION: update energy void entry in energy void file
  1143. X/
  1144. X/ AUTHOR: E. A. Estes, 12/4/85
  1145. X/
  1146. X/ ARGUMENTS:
  1147. X/    struct energyvoid *vp - pointer to structure to write to file
  1148. X/    long loc - location in file to update
  1149. X/
  1150. X/ RETURN VALUE: none
  1151. X/
  1152. X/ MODULES CALLED: fseek(), fwrite(), fflush()
  1153. X/
  1154. X/ GLOBAL INPUTS: *Energyvoidfp
  1155. X/
  1156. X/ GLOBAL OUTPUTS: none
  1157. X/
  1158. X/ DESCRIPTION:
  1159. X/    Write out energy void structure at specified location.
  1160. X/
  1161. X/************************************************************************/
  1162. X
  1163. Xwritevoid(vp, loc)
  1164. Xregister struct energyvoid    *vp;
  1165. Xlong    loc;
  1166. X{
  1167. X
  1168. X    fseek(Energyvoidfp, loc, 0);
  1169. X    fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
  1170. X    fflush(Energyvoidfp);
  1171. X}
  1172. X/* */
  1173. X/************************************************************************
  1174. X/
  1175. X/ FUNCTION NAME: allocvoid()
  1176. X/
  1177. X/ FUNCTION: allocate space for a new energy void
  1178. X/
  1179. X/ AUTHOR: E. A. Estes, 12/4/85
  1180. X/
  1181. X/ ARGUMENTS: none
  1182. X/
  1183. X/ RETURN VALUE: location of new energy void space
  1184. X/
  1185. X/ MODULES CALLED: fread(), fseek()
  1186. X/
  1187. X/ GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
  1188. X/
  1189. X/ GLOBAL OUTPUTS: none
  1190. X/
  1191. X/ DESCRIPTION:
  1192. X/    Search energy void file for an inactive entry and return its
  1193. X/    location.
  1194. X/    If no inactive ones are found, return one more than last location.
  1195. X/
  1196. X/************************************************************************/
  1197. X
  1198. Xlong
  1199. Xallocvoid()
  1200. X{
  1201. Xlong    loc = 0L;        /* location of new energy void */
  1202. X
  1203. X    fseek(Energyvoidfp, 0L, 0);
  1204. X    while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
  1205. X    if (Enrgyvoid.ev_active)
  1206. X        loc += SZ_VOIDSTRUCT;
  1207. X    else
  1208. X        break;
  1209. X
  1210. X    return(loc);
  1211. X}
  1212. !EOR!
  1213. echo x - gamesupport.c
  1214. sed 's/^X//' > gamesupport.c << '!EOR!'
  1215. X/*
  1216. X * gamesupport.c - auxiliary routines for support of Phantasia
  1217. X */
  1218. X
  1219. X#include "include.h"
  1220. X
  1221. X/************************************************************************
  1222. X/
  1223. X/ FUNCTION NAME: changestats()
  1224. X/
  1225. X/ FUNCTION: examine/change statistics for a player
  1226. X/
  1227. X/ AUTHOR: E. A. Estes, 12/4/85
  1228. X/
  1229. X/ ARGUMENTS:
  1230. X/    bool ingameflag - set if called while playing game (Wizard only)
  1231. X/
  1232. X/ RETURN VALUE: none
  1233. X/
  1234. X/ MODULES CALLED: freerecord(), writerecord(), descrstatus(), truncstring(), 
  1235. X/    time(), more(), wmove(), wclear(), strcmp(), printw(), strcpy(), 
  1236. X/    infloat(), waddstr(), cleanup(), findname(), userlist(), mvprintw(), 
  1237. X/    localtime(), getanswer(), descrtype(), getstring()
  1238. X/
  1239. X/ GLOBAL INPUTS: LINES, *Login, Other, Wizard, Player, *stdscr, Databuf[], 
  1240. X/    Fileloc
  1241. X/
  1242. X/ GLOBAL OUTPUTS: Echo
  1243. X/
  1244. X/ DESCRIPTION:
  1245. X/    Prompt for player name to examine/change.
  1246. X/    If the name is NULL, print a list of all players.
  1247. X/    If we are called from within the game, check for the
  1248. X/    desired name being the same as the current player's name.
  1249. X/    Only the 'Wizard' may alter players.
  1250. X/    Items are changed only if a non-zero value is specified.
  1251. X/    To change an item to 0, use 0.1; it will be truncated later.
  1252. X/
  1253. X/    Players may alter their names and passwords, if the following
  1254. X/    are true:
  1255. X/        - current login matches the character's logins
  1256. X/        - the password is known
  1257. X/        - the player is not in the middle of the game (ingameflag == FALSE)
  1258. X/
  1259. X/    The last condition is imposed for two reasons:
  1260. X/        - the game could possibly get a bit hectic if a player were
  1261. X/          continually changing his/her name
  1262. X/        - another player structure would be necessary to check for names
  1263. X/          already in use
  1264. X/
  1265. X/************************************************************************/
  1266. X
  1267. Xchangestats(ingameflag)
  1268. Xbool    ingameflag;
  1269. X{
  1270. Xstatic char    flag[2] = /* for printing values of bools */
  1271. X    {'F', 'T'};
  1272. Xregister struct player    *playerp;/* pointer to structure to alter */
  1273. Xregister char    *prompt;    /* pointer to prompt string */
  1274. Xint    c;            /* input */
  1275. Xint    today;            /* day of year of today */
  1276. Xint    temp;            /* temporary variable */
  1277. Xlong    loc;            /* location in player file */
  1278. Xlong    now;            /* time now */
  1279. Xdouble    dtemp;            /* temporary variable */
  1280. Xbool    *bptr;            /* pointer to bool item to change */
  1281. Xdouble    *dptr;            /* pointer to double item to change */
  1282. Xshort    *sptr;            /* pointer to short item to change */
  1283. X
  1284. X    clear();
  1285. X
  1286. X    for (;;)
  1287. X    /* get name of player to examine/alter */
  1288. X    {
  1289. X    mvaddstr(5, 0, "Which character do you want to look at ? ");
  1290. X    getstring(Databuf, SZ_DATABUF);
  1291. X    truncstring(Databuf);
  1292. X
  1293. X    if (Databuf[0] == '\0')
  1294. X        userlist(ingameflag);
  1295. X    else
  1296. X        break;
  1297. X    }
  1298. X
  1299. X    loc = -1L;
  1300. X
  1301. X    if (!ingameflag)
  1302. X    /* use 'Player' structure */
  1303. X    playerp = &Player;
  1304. X    else if (strcmp(Databuf, Player.p_name) == 0)
  1305. X    /* alter/examine current player */
  1306. X    {
  1307. X    playerp = &Player;
  1308. X    loc = Fileloc;
  1309. X    }
  1310. X    else
  1311. X    /* use 'Other' structure */
  1312. X    playerp = &Other;
  1313. X
  1314. X    /* find player on file */
  1315. X    if (loc < 0L && (loc = findname(Databuf, playerp)) < 0L)
  1316. X    /* didn't find player */
  1317. X    {
  1318. X    clear();
  1319. X    mvaddstr(11, 0, "Not found.");
  1320. X    return;
  1321. X    }
  1322. X
  1323. X    time(&now);
  1324. X    today = localtime(&now)->tm_yday;
  1325. X
  1326. X    clear();
  1327. X
  1328. X    for (;;)
  1329. X    /* print player structure, and prompt for action */
  1330. X    {
  1331. X    mvprintw(0, 0,"A:Name         %s\n", playerp->p_name);
  1332. X
  1333. X    if (Wizard)
  1334. X        printw("B:Password     %s\n", playerp->p_password);
  1335. X    else
  1336. X        addstr("B:Password     XXXXXXXX\n");
  1337. X
  1338. X    printw(" :Login        %s\n", playerp->p_login);
  1339. X
  1340. X    printw("C:Experience   %.0f\n", playerp->p_experience);
  1341. X    printw("D:Level        %.0f\n", playerp->p_level);
  1342. X    printw("E:Strength     %.0f\n", playerp->p_strength);
  1343. X    printw("F:Sword        %.0f\n", playerp->p_sword);
  1344. X    printw(" :Might        %.0f\n", playerp->p_might);
  1345. X    printw("G:Energy       %.0f\n", playerp->p_energy);
  1346. X    printw("H:Max-Energy   %.0f\n", playerp->p_maxenergy);
  1347. X    printw("I:Shield       %.0f\n", playerp->p_shield);
  1348. X    printw("J:Quickness    %.0f\n", playerp->p_quickness);
  1349. X    printw("K:Quicksilver  %.0f\n", playerp->p_quksilver);
  1350. X    printw(" :Speed        %.0f\n", playerp->p_speed);
  1351. X    printw("L:Magic Level  %.0f\n", playerp->p_magiclvl);
  1352. X    printw("M:Mana         %.0f\n", playerp->p_mana);
  1353. X    printw("N:Brains       %.0f\n", playerp->p_brains);
  1354. X
  1355. X    if (Wizard || playerp->p_specialtype != SC_VALAR)
  1356. X        mvaddstr(0, 40, descrstatus(playerp));
  1357. X
  1358. X    mvprintw(1, 40, "O:Poison       %0.3f\n", playerp->p_poison);
  1359. X    mvprintw(2, 40, "P:Gold         %.0f\n", playerp->p_gold);
  1360. X    mvprintw(3, 40, "Q:Gem          %.0f\n", playerp->p_gems);
  1361. X    mvprintw(4, 40, "R:Sin          %0.3f\n", playerp->p_sin);
  1362. X    if (Wizard)
  1363. X        {
  1364. X        mvprintw(5, 40, "S:X-coord      %.0f\n", playerp->p_x);
  1365. X        mvprintw(6, 40, "T:Y-coord      %.0f\n", playerp->p_y);
  1366. X        }
  1367. X    else
  1368. X        {
  1369. X        mvaddstr(5, 40, "S:X-coord      ?\n");
  1370. X        mvaddstr(6, 40, "T:Y-coord      ?\n");
  1371. X        }
  1372. X
  1373. X    mvprintw(7, 40, "U:Age          %ld\n", playerp->p_age);
  1374. X    mvprintw(8, 40, "V:Degenerated  %d\n", playerp->p_degenerated);
  1375. X
  1376. X    mvprintw(9, 40, "W:Type         %d (%s)\n",
  1377. X        playerp->p_type, descrtype(playerp, FALSE) + 1);
  1378. X    mvprintw(10, 40, "X:Special Type %d\n", playerp->p_specialtype);
  1379. X    mvprintw(11, 40, "Y:Lives        %d\n", playerp->p_lives);
  1380. X    mvprintw(12, 40, "Z:Crowns       %d\n", playerp->p_crowns);
  1381. X    mvprintw(13, 40, "0:Charms       %d\n", playerp->p_charms);
  1382. X    mvprintw(14, 40, "1:Amulets      %d\n", playerp->p_amulets);
  1383. X    mvprintw(15, 40, "2:Holy Water   %d\n", playerp->p_holywater);
  1384. X
  1385. X    temp = today - playerp->p_lastused;
  1386. X    if (temp < 0)
  1387. X        /* last year */
  1388. X        temp += 365;
  1389. X    mvprintw(16, 40, "3:Lastused     %d  (%d)\n", playerp->p_lastused,  temp);
  1390. X
  1391. X    mvprintw(18, 8, "4:Blessed %c  5:Palantir %c  6:Virgin %c  7:Blind %c",
  1392. X        flag[playerp->p_palantir],
  1393. X        flag[playerp->p_blessing],
  1394. X        flag[playerp->p_virgin],
  1395. X        flag[playerp->p_blindness]);
  1396. X
  1397. X    if (!Wizard)
  1398. X        mvprintw(19, 8, "8:Ring    %c",
  1399. X        flag[playerp->p_ring.ring_type != R_NONE]);
  1400. X    else
  1401. X        mvprintw(19, 8, "8:Ring    %d  9:Duration %d",
  1402. X        playerp->p_ring.ring_type, playerp->p_ring.ring_duration);
  1403. X
  1404. X    if (!Wizard
  1405. X        /* not wizard */
  1406. X        && (ingameflag || strcmp(Login, playerp->p_login) != 0))
  1407. X        /* in game or not examining own character */
  1408. X        {
  1409. X        if (ingameflag)
  1410. X        {
  1411. X        more(LINES - 1);
  1412. X        clear();
  1413. X        return;
  1414. X        }
  1415. X        else
  1416. X        cleanup(TRUE);
  1417. X        /*NOTREACHED*/
  1418. X        }
  1419. X
  1420. X    mvaddstr(20, 0, "!:Quit       ?:Delete");
  1421. X    mvaddstr(21, 0, "What would you like to change ? ");
  1422. X
  1423. X    if (Wizard)
  1424. X        c = getanswer(" ", TRUE);
  1425. X    else
  1426. X        /* examining own player; allow to change name and password */
  1427. X        c = getanswer("!BA", FALSE);
  1428. X
  1429. X    switch (c)
  1430. X        {
  1431. X        case 'A':    /* change name */
  1432. X        case 'B':    /* change password */
  1433. X        if (!Wizard)
  1434. X            /* prompt for password */
  1435. X            {
  1436. X            mvaddstr(23, 0, "Password ? ");
  1437. X            Echo = FALSE;
  1438. X            getstring(Databuf, 9);
  1439. X            Echo = TRUE;
  1440. X            if (strcmp(Databuf, playerp->p_password) != 0)
  1441. X            continue;
  1442. X            }
  1443. X            
  1444. X        if (c == 'A')
  1445. X            /* get new name */
  1446. X            {
  1447. X            mvaddstr(23, 0, "New name: ");
  1448. X            getstring(Databuf, SZ_NAME);
  1449. X            truncstring(Databuf);
  1450. X            if (Databuf[0] != '\0')
  1451. X            if (Wizard || findname(Databuf, &Other) < 0L)
  1452. X                strcpy(playerp->p_name, Databuf);
  1453. X            }
  1454. X        else
  1455. X            /* get new password */
  1456. X            {
  1457. X            if (!Wizard)
  1458. X            Echo = FALSE;
  1459. X
  1460. X            do
  1461. X            /* get two copies of new password until they match */
  1462. X            {
  1463. X            /* get first copy */
  1464. X            mvaddstr(23, 0, "New password ? ");
  1465. X            getstring(Databuf, SZ_PASSWORD);
  1466. X            if (Databuf[0] == '\0')
  1467. X                break;
  1468. X
  1469. X            /* get second copy */
  1470. X            mvaddstr(23, 0, "One more time ? ");
  1471. X            getstring(playerp->p_password, SZ_PASSWORD);
  1472. X            }
  1473. X            while (strcmp(playerp->p_password, Databuf) != 0);
  1474. X
  1475. X            Echo = TRUE;
  1476. X            }
  1477. X
  1478. X        continue;
  1479. X
  1480. X        case 'C':    /* change experience */
  1481. X        prompt = "experience";
  1482. X        dptr = &playerp->p_experience;
  1483. X        goto DALTER;
  1484. X
  1485. X        case 'D':    /* change level */
  1486. X        prompt = "level";
  1487. X        dptr = &playerp->p_level;
  1488. X        goto DALTER;
  1489. X
  1490. X        case 'E':    /* change strength */
  1491. X        prompt = "strength";
  1492. X        dptr = &playerp->p_strength;
  1493. X        goto DALTER;
  1494. X
  1495. X        case 'F':    /* change swords */
  1496. X        prompt = "sword";
  1497. X        dptr = &playerp->p_sword;
  1498. X        goto DALTER;
  1499. X
  1500. X        case 'G':    /* change energy */
  1501. X        prompt = "energy";
  1502. X        dptr = &playerp->p_energy;
  1503. X        goto DALTER;
  1504. X
  1505. X        case 'H':    /* change maximum energy */
  1506. X        prompt = "max energy";
  1507. X        dptr = &playerp->p_maxenergy;
  1508. X        goto DALTER;
  1509. X
  1510. X        case 'I':    /* change shields */
  1511. X        prompt = "shield";
  1512. X        dptr = &playerp->p_shield;
  1513. X        goto DALTER;
  1514. X
  1515. X        case 'J':    /* change quickness */
  1516. X        prompt = "quickness";
  1517. X        dptr = &playerp->p_quickness;
  1518. X        goto DALTER;
  1519. X
  1520. X        case 'K':    /* change quicksilver */
  1521. X        prompt = "quicksilver";
  1522. X        dptr = &playerp->p_quksilver;
  1523. X        goto DALTER;
  1524. X
  1525. X        case 'L':    /* change magic */
  1526. X        prompt = "magic level";
  1527. X        dptr = &playerp->p_magiclvl;
  1528. X        goto DALTER;
  1529. X
  1530. X        case 'M':    /* change mana */
  1531. X        prompt = "mana";
  1532. X        dptr = &playerp->p_mana;
  1533. X        goto DALTER;
  1534. X
  1535. X        case 'N':    /* change brains */
  1536. X        prompt = "brains";
  1537. X        dptr = &playerp->p_brains;
  1538. X        goto DALTER;
  1539. X
  1540. X        case 'O':    /* change poison */
  1541. X        prompt = "poison";
  1542. X        dptr = &playerp->p_poison;
  1543. X        goto DALTER;
  1544. X
  1545. X        case 'P':    /* change gold */
  1546. X        prompt = "gold";
  1547. X        dptr = &playerp->p_gold;
  1548. X        goto DALTER;
  1549. X
  1550. X        case 'Q':    /* change gems */
  1551. X        prompt = "gems";
  1552. X        dptr = &playerp->p_gems;
  1553. X        goto DALTER;
  1554. X
  1555. X        case 'R':    /* change sin */
  1556. X        prompt = "sin";
  1557. X        dptr = &playerp->p_sin;
  1558. X        goto DALTER;
  1559. X
  1560. X        case 'S':    /* change x coord */
  1561. X        prompt = "x";
  1562. X        dptr = &playerp->p_x;
  1563. X        goto DALTER;
  1564. X
  1565. X        case 'T':    /* change y coord */
  1566. X        prompt = "y";
  1567. X        dptr = &playerp->p_y;
  1568. X        goto DALTER;
  1569. X
  1570. X        case 'U':    /* change age */
  1571. X        mvprintw(23, 0, "age = %ld; age = ", playerp->p_age);
  1572. X        dtemp = infloat();
  1573. X        if (dtemp != 0.0)
  1574. X            playerp->p_age = (long) dtemp;
  1575. X        continue;
  1576. X
  1577. X        case 'V':    /* change degen */
  1578. X        mvprintw(23, 0, "degen = %d; degen = ", playerp->p_degenerated);
  1579. X        dtemp = infloat();
  1580. X        if (dtemp != 0.0)
  1581. X            playerp->p_degenerated = (int) dtemp;
  1582. X        continue;
  1583. X
  1584. X        case 'W':    /* change type */
  1585. X        prompt = "type";
  1586. X        sptr = &playerp->p_type;
  1587. X        goto SALTER;
  1588. X
  1589. X        case 'X':    /* change special type */
  1590. X        prompt = "special type";
  1591. X        sptr = &playerp->p_specialtype;
  1592. X        goto SALTER;
  1593. X
  1594. X        case 'Y':    /* change lives */
  1595. X        prompt = "lives";
  1596. X        sptr = &playerp->p_lives;
  1597. X        goto SALTER;
  1598. X
  1599. X        case 'Z':    /* change crowns */
  1600. X        prompt = "crowns";
  1601. X        sptr = &playerp->p_crowns;
  1602. X        goto SALTER;
  1603. X
  1604. X        case '0':    /* change charms */
  1605. X        prompt = "charm";
  1606. X        sptr = &playerp->p_charms;
  1607. X        goto SALTER;
  1608. X
  1609. X        case '1':    /* change amulet */
  1610. X        prompt = "amulet";
  1611. X        sptr = &playerp->p_amulets;
  1612. X        goto SALTER;
  1613. X
  1614. X        case '2':    /* change holy water */
  1615. X        prompt = "holy water";
  1616. X        sptr = &playerp->p_holywater;
  1617. X        goto SALTER;
  1618. X
  1619. X        case '3':    /* change last-used */
  1620. X        prompt = "last-used";
  1621. X        sptr = &playerp->p_lastused;
  1622. X        goto SALTER;
  1623. X
  1624. X        case '4':    /* change palantir */
  1625. X        prompt = "palantir";
  1626. X        bptr = &playerp->p_palantir;
  1627. X        goto BALTER;
  1628. X
  1629. X        case '5':    /* change blessing */
  1630. X        prompt = "blessing";
  1631. X        bptr = &playerp->p_blessing;
  1632. X        goto BALTER;
  1633. X
  1634. X        case '6':    /* change virgin */
  1635. X        prompt = "virgin";
  1636. X        bptr = &playerp->p_virgin;
  1637. X        goto BALTER;
  1638. X
  1639. X        case '7':    /* change blindness */
  1640. X        prompt = "blindness";
  1641. X        bptr = &playerp->p_blindness;
  1642. X        goto BALTER;
  1643. X
  1644. X        case '8':    /* change ring type */
  1645. X        prompt = "ring-type";
  1646. X        sptr = &playerp->p_ring.ring_type;
  1647. X        goto SALTER;
  1648. X
  1649. X        case '9':    /* change ring duration */
  1650. X        prompt = "ring-duration";
  1651. X        sptr = &playerp->p_ring.ring_duration;
  1652. X        goto SALTER;
  1653. X
  1654. X        case '!':    /* quit, update */
  1655. X        if (Wizard &&
  1656. X            (!ingameflag || playerp != &Player))
  1657. X            /* turn off status if not modifying self */
  1658. X            {
  1659. X            playerp->p_status = S_OFF;
  1660. X            playerp->p_tampered = T_OFF;
  1661. X            }
  1662. X
  1663. X        writerecord(playerp, loc);
  1664. X        clear();
  1665. X        return;
  1666. X
  1667. X        case '?':    /* delete player */
  1668. X        if (ingameflag && playerp == &Player)
  1669. X            /* cannot delete self */
  1670. X            continue;
  1671. X
  1672. X        freerecord(playerp, loc);
  1673. X        clear();
  1674. X        return;
  1675. X
  1676. X        default:
  1677. X        continue;
  1678. X        }
  1679. XDALTER:
  1680. X    mvprintw(23, 0, "%s = %f; %s = ", prompt, *dptr, prompt);
  1681. X    dtemp = infloat();
  1682. X    if (dtemp != 0.0)
  1683. X        *dptr = dtemp;
  1684. X    continue;
  1685. X
  1686. XSALTER:
  1687. X    mvprintw(23, 0, "%s = %d; %s = ", prompt, *sptr, prompt);
  1688. X    dtemp = infloat();
  1689. X    if (dtemp != 0.0)
  1690. X        *sptr = (short) dtemp;
  1691. X    continue;
  1692. X
  1693. XBALTER:
  1694. X    mvprintw(23, 0, "%s = %c; %s = ", prompt, flag[*bptr], prompt);
  1695. X    c = getanswer("\nTF", TRUE);
  1696. X    if (c == 'T')
  1697. X        *bptr = TRUE;
  1698. X    else if (c == 'F')
  1699. X        *bptr = FALSE;
  1700. X    continue;
  1701. X    }
  1702. X}
  1703. X/* */
  1704. X/************************************************************************
  1705. X/
  1706. X/ FUNCTION NAME: monstlist()
  1707. X/
  1708. X/ FUNCTION: print a monster listing
  1709. X/
  1710. X/ AUTHOR: E. A. Estes, 2/27/86
  1711. X/
  1712. X/ ARGUMENTS: none
  1713. X/
  1714. X/ RETURN VALUE: none
  1715. X/
  1716. X/ MODULES CALLED: puts(), fread(), fseek(), printf()
  1717. X/
  1718. X/ GLOBAL INPUTS: Curmonster, *Monstfp
  1719. X/
  1720. X/ GLOBAL OUTPUTS: none
  1721. X/
  1722. X/ DESCRIPTION:
  1723. X/    Read monster file, and print a monster listing on standard output.
  1724. X/
  1725. X/************************************************************************/
  1726. X
  1727. Xmonstlist()
  1728. X{
  1729. Xregister int     count = 0;        /* count in file */
  1730. X
  1731. X    puts(" #)  Name                 Str  Brain  Quick  Energy  Exper  Treas  Type  Flock%\n");
  1732. X    fseek(Monstfp, 0L, 0);
  1733. X    while (fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp) == 1)
  1734. X    printf("%2d)  %-20.20s%4.0f   %4.0f     %2.0f   %5.0f  %5.0f     %2d    %2d     %3.0f\n", count++,
  1735. X        Curmonster.m_name, Curmonster.m_strength, Curmonster.m_brains,
  1736. X        Curmonster.m_speed, Curmonster.m_energy, Curmonster.m_experience,
  1737. X        Curmonster.m_treasuretype, Curmonster.m_type, Curmonster.m_flock);
  1738. X}
  1739. X/* */
  1740. X/************************************************************************
  1741. X/
  1742. X/ FUNCTION NAME: scorelist()
  1743. X/
  1744. X/ FUNCTION: print player score board
  1745. X/
  1746. X/ AUTHOR: E. A. Estes, 12/4/85
  1747. X/
  1748. X/ ARGUMENTS: none
  1749. X/
  1750. X/ RETURN VALUE: none
  1751. X/
  1752. X/ MODULES CALLED: fread(), fopen(), printf(), fclose()
  1753. X/
  1754. X/ GLOBAL INPUTS: Scorefile[]
  1755. X/
  1756. X/ GLOBAL OUTPUTS: none
  1757. X/
  1758. X/ DESCRIPTION:
  1759. X/    Read the scoreboard file and print the contents.
  1760. X/
  1761. X/************************************************************************/
  1762. X
  1763. Xscorelist()
  1764. X{
  1765. Xstruct    scoreboard    sbuf;    /* for reading entries */
  1766. Xregister FILE    *fp;        /* to open the file */
  1767. X
  1768. X    if ((fp = fopen(Scorefile, "r")) != NULL)
  1769. X    {
  1770. X    while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
  1771. X        printf("%-20s   (%-9s)  Level: %6.0f  Type: %s\n",
  1772. X        sbuf.sb_name, sbuf.sb_login, sbuf.sb_level, sbuf.sb_type);
  1773. X    fclose(fp);
  1774. X    }
  1775. X}
  1776. X/* */
  1777. X/************************************************************************
  1778. X/
  1779. X/ FUNCTION NAME: activelist()
  1780. X/
  1781. X/ FUNCTION: print list of active players to standard output
  1782. X/
  1783. X/ AUTHOR: E. A. Estes, 3/7/86
  1784. X/
  1785. X/ ARGUMENTS: none
  1786. X/
  1787. X/ RETURN VALUE: none
  1788. X/
  1789. X/ MODULES CALLED: descrstatus(), fread(), fseek(), printf(), descrtype()
  1790. X/
  1791. X/ GLOBAL INPUTS: Other, *Playersfp
  1792. X/
  1793. X/ GLOBAL OUTPUTS: none
  1794. X/
  1795. X/ DESCRIPTION:
  1796. X/    Read player file, and print list of active records to standard output.
  1797. X/
  1798. X/************************************************************************/
  1799. X
  1800. Xactivelist()
  1801. X{
  1802. X    fseek(Playersfp, 0L, 0);
  1803. X    printf("Current characters on file are:\n\n");
  1804. X
  1805. X    while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
  1806. X    if (Other.p_status != S_NOTUSED)
  1807. X        printf("%-20s   (%-9s)  Level: %6.0f  %s  (%s)\n",
  1808. X        Other.p_name, Other.p_login, Other.p_level,
  1809. X        descrtype(&Other, FALSE), descrstatus(&Other));
  1810. X
  1811. X}
  1812. X/* */
  1813. X/************************************************************************
  1814. X/
  1815. X/ FUNCTION NAME: purgeoldplayers()
  1816. X/
  1817. X/ FUNCTION: purge inactive players from player file
  1818. X/
  1819. X/ AUTHOR: E. A. Estes, 12/4/85
  1820. X/
  1821. X/ ARGUMENTS: none
  1822. X/
  1823. X/ RETURN VALUE: none
  1824. X/
  1825. X/ MODULES CALLED: freerecord(), time(), fread(), fseek(), localtime()
  1826. X/
  1827. X/ GLOBAL INPUTS: Other, *Playersfp
  1828. X/
  1829. X/ GLOBAL OUTPUTS: none
  1830. X/
  1831. X/ DESCRIPTION:
  1832. X/    Delete characters which have not been used with the last
  1833. X/    three weeks.
  1834. X/
  1835. X/************************************************************************/
  1836. X
  1837. Xpurgeoldplayers()
  1838. X{
  1839. Xint    today;        /* day of year for today */
  1840. Xint    daysold;    /* how many days since the character has been used */
  1841. Xlong    ltime;        /* time in seconds */
  1842. Xlong    loc = 0L;    /* location in file */
  1843. X
  1844. X    time(<ime);
  1845. X    today = localtime(<ime)->tm_yday;
  1846. X
  1847. X    for (;;)
  1848. X    {
  1849. X    fseek(Playersfp, loc, 0);
  1850. X    if (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) != 1)
  1851. X        break;
  1852. X
  1853. X    daysold = today - Other.p_lastused;
  1854. X    if (daysold < 0)
  1855. X        daysold += 365;
  1856. X
  1857. X    if (daysold > N_DAYSOLD)
  1858. X        /* player hasn't been used in a while; delete */
  1859. X        freerecord(&Other, loc);
  1860. X
  1861. X    loc += SZ_PLAYERSTRUCT;
  1862. X    }
  1863. X}
  1864. X/* */
  1865. X/************************************************************************
  1866. X/
  1867. X/ FUNCTION NAME: enterscore()
  1868. X/
  1869. X/ FUNCTION: enter player into scoreboard
  1870. X/
  1871. X/ AUTHOR: E. A. Estes, 12/4/85
  1872. X/
  1873. X/ ARGUMENTS: none
  1874. X/
  1875. X/ RETURN VALUE: none
  1876. X/
  1877. X/ MODULES CALLED: fread(), fseek(), fopen(), error(), strcmp(), fclose(), 
  1878. X/    strcpy(), fwrite(), descrtype()
  1879. X/
  1880. X/ GLOBAL INPUTS: Player, Scorefile[]
  1881. X/
  1882. X/ GLOBAL OUTPUTS: none
  1883. X/
  1884. X/ DESCRIPTION:
  1885. X/    The scoreboard keeps track of the highest character on a
  1886. X/    per-login basis.
  1887. X/    Search the scoreboard for an entry for the current login,
  1888. X/    if an entry is found, and it is lower than the current player,
  1889. X/    replace it, otherwise create an entry.
  1890. X/
  1891. X/************************************************************************/
  1892. X
  1893. Xenterscore()
  1894. X{
  1895. Xstruct    scoreboard sbuf;        /* buffer to read in scoreboard entries */
  1896. XFILE    *fp;                /* to open scoreboard file */
  1897. Xlong    loc = 0L;            /* location in scoreboard file */
  1898. Xbool    found = FALSE;            /* set if we found an entry for this login */
  1899. X
  1900. X    if ((fp = fopen(Scorefile, "r+")) != NULL)
  1901. X    {
  1902. X    while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
  1903. X        if (strcmp(Player.p_login, sbuf.sb_login) == 0)
  1904. X        {
  1905. X        found = TRUE;
  1906. X        break;
  1907. X        }
  1908. X        else
  1909. X        loc += SZ_SCORESTRUCT;
  1910. X    }
  1911. X    else
  1912. X    {
  1913. X    error(Scorefile);
  1914. X    /*NOTREACHED*/
  1915. X    }
  1916. X
  1917. X    /*
  1918. X     * At this point, 'loc' will either indicate a point beyond
  1919. X     * the end of file, or the place where the previous entry
  1920. X     * was found.
  1921. X     */
  1922. X
  1923. X    if ((!found) || Player.p_level > sbuf.sb_level)
  1924. X    /* put new entry in for this login */
  1925. X    {
  1926. X    strcpy(sbuf.sb_login, Player.p_login);
  1927. X    strcpy(sbuf.sb_name, Player.p_name);
  1928. X    sbuf.sb_level = Player.p_level;
  1929. X    strcpy(sbuf.sb_type, descrtype(&Player, TRUE));
  1930. X    }
  1931. X
  1932. X    /* update entry */
  1933. X    fseek(fp, loc, 0);
  1934. X    fwrite((char *) &sbuf, SZ_SCORESTRUCT, 1, fp);
  1935. X    fclose(fp);
  1936. X}
  1937. !EOR!
  1938. echo x - io.c
  1939. sed 's/^X//' > io.c << '!EOR!'
  1940. X/*
  1941. X * io.c - input/output routines for Phantasia
  1942. X */
  1943. X
  1944. X#include "include.h"
  1945. X
  1946. X/************************************************************************
  1947. X/
  1948. X/ FUNCTION NAME: getstring()
  1949. X/
  1950. X/ FUNCTION: read a string from operator
  1951. X/
  1952. X/ AUTHOR: E. A. Estes, 12/4/85
  1953. X/
  1954. X/ ARGUMENTS:
  1955. X/    char *cp - pointer to buffer area to fill
  1956. X/    int mx - maximum number of characters to put in buffer
  1957. X/
  1958. X/ RETURN VALUE: none
  1959. X/
  1960. X/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(), 
  1961. X/    wclrtoeol()
  1962. X/
  1963. X/ GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
  1964. X/
  1965. X/ GLOBAL OUTPUTS: _iob[]
  1966. X/
  1967. X/ DESCRIPTION:
  1968. X/    Read a string from the keyboard.
  1969. X/    This routine is specially designed to:
  1970. X/
  1971. X/        - strip non-printing characters (unless Wizard)
  1972. X/        - echo, if desired
  1973. X/        - redraw the screen if CH_REDRAW is entered
  1974. X/        - read in only 'mx - 1' characters or less characters
  1975. X/        - nul-terminate string, and throw away newline
  1976. X/
  1977. X/    'mx' is assumed to be at least 2.
  1978. X/
  1979. X/************************************************************************/
  1980. X
  1981. Xgetstring(cp, mx)
  1982. Xregister char    *cp;
  1983. Xregister int    mx;
  1984. X{
  1985. Xregister char    *inptr;        /* pointer into string for next string */
  1986. Xint    x, y;            /* original x, y coordinates on screen */
  1987. Xint    ch;            /* input */
  1988. X
  1989. X    getyx(stdscr, y, x);    /* get coordinates on screen */
  1990. X    inptr = cp;
  1991. X    *inptr = '\0';        /* clear string to start */
  1992. X    --mx;            /* reserve room in string for nul terminator */
  1993. X
  1994. X    do
  1995. X    /* get characters and process */
  1996. X    {
  1997. X    if (Echo)
  1998. X        mvaddstr(y, x, cp);    /* print string on screen */
  1999. X    clrtoeol();        /* clear any data after string */
  2000. X    refresh();        /* update screen */
  2001. X
  2002. X    ch = getchar();        /* get character */
  2003. X
  2004. X    switch (ch)
  2005. X        {
  2006. X        case CH_ERASE:    /* back up one character */
  2007. X        if (inptr > cp)
  2008. X            --inptr;
  2009. X        break;
  2010. X
  2011. X        case CH_KILL:    /* back up to original location */
  2012. X        inptr = cp;
  2013. X        break;
  2014. X
  2015. X        case CH_NEWLINE:    /* terminate string */
  2016. X        break;
  2017. X
  2018. X        case CH_REDRAW:    /* redraw screen */
  2019. X        clearok(stdscr, TRUE);
  2020. X        continue;
  2021. X
  2022. X        default:        /* put data in string */
  2023. X        if (ch >= ' ' || Wizard)
  2024. X            /* printing char; put in string */
  2025. X            *inptr++ = ch;
  2026. X        }
  2027. X
  2028. X    *inptr = '\0';        /* terminate string */
  2029. X    }
  2030. X    while (ch != CH_NEWLINE && inptr < cp + mx);
  2031. X}
  2032. X/* */
  2033. X/************************************************************************
  2034. X/
  2035. X/ FUNCTION NAME: more()
  2036. X/
  2037. X/ FUNCTION: pause and prompt player
  2038. X/
  2039. X/ AUTHOR: E. A. Estes, 12/4/85
  2040. X/
  2041. X/ ARGUMENTS:
  2042. X/    int where - line on screen on which to pause
  2043. X/
  2044. X/ RETURN VALUE: none
  2045. X/
  2046. X/ MODULES CALLED: wmove(), waddstr(), getanswer()
  2047. X/
  2048. X/ GLOBAL INPUTS: *stdscr
  2049. X/
  2050. X/ GLOBAL OUTPUTS: none
  2051. X/
  2052. X/ DESCRIPTION:
  2053. X/    Print a message, and wait for a space character.
  2054. X/
  2055. X/************************************************************************/
  2056. X
  2057. Xmore(where)
  2058. Xint    where;
  2059. X{
  2060. X    mvaddstr(where, 0, "-- more --");
  2061. X    getanswer(" ", FALSE);
  2062. X}
  2063. X/* */
  2064. X/************************************************************************
  2065. X/
  2066. X/ FUNCTION NAME: infloat()
  2067. X/
  2068. X/ FUNCTION: input a floating point number from operator
  2069. X/
  2070. X/ AUTHOR: E. A. Estes, 12/4/85
  2071. X/
  2072. X/ ARGUMENTS: none
  2073. X/
  2074. X/ RETURN VALUE: floating point number from operator
  2075. X/
  2076. X/ MODULES CALLED: sscanf(), getstring()
  2077. X/
  2078. X/ GLOBAL INPUTS: Databuf[]
  2079. X/
  2080. X/ GLOBAL OUTPUTS: none
  2081. X/
  2082. X/ DESCRIPTION:
  2083. X/    Read a string from player, and scan for a floating point
  2084. X/    number.
  2085. X/    If no valid number is found, return 0.0.
  2086. X/
  2087. X/************************************************************************/
  2088. X
  2089. Xdouble
  2090. Xinfloat()
  2091. X{
  2092. Xdouble    result;        /* return value */
  2093. X
  2094. X    getstring(Databuf, SZ_DATABUF);
  2095. X    if (sscanf(Databuf, "%F", &result) < 1)
  2096. X    /* no valid number entered */
  2097. X    result = 0.0;
  2098. X
  2099. X    return(result);
  2100. X}
  2101. X/* */
  2102. X/************************************************************************
  2103. X/
  2104. X/ FUNCTION NAME: inputoption()
  2105. X/
  2106. X/ FUNCTION: input an option value from player
  2107. X/
  2108. X/ AUTHOR: E. A. Estes, 12/4/85
  2109. X/
  2110. X/ ARGUMENTS: none
  2111. X/
  2112. X/ RETURN VALUE: none
  2113. X/
  2114. X/ MODULES CALLED: floor(), random(), getanswer()
  2115. X/
  2116. X/ GLOBAL INPUTS: Player
  2117. X/
  2118. X/ GLOBAL OUTPUTS: Player
  2119. X/
  2120. X/ DESCRIPTION:
  2121. X/    Age increases with every move.
  2122. X/    Refresh screen, and get a single character option from player.
  2123. X/    Return a random value if player's ring has gone bad.
  2124. X/
  2125. X/************************************************************************/
  2126. X
  2127. Xinputoption()
  2128. X{
  2129. X    ++Player.p_age;        /* increase age */
  2130. X
  2131. X    if (Player.p_ring.ring_type != R_SPOILED)
  2132. X    /* ring ok */
  2133. X    return(getanswer("T ", TRUE));
  2134. X    else
  2135. X    /* bad ring */
  2136. X    {
  2137. X    getanswer(" ", TRUE);
  2138. X    return((int) ROLL(0.0, 5.0) + '0');
  2139. X    }
  2140. X}
  2141. X/* */
  2142. X/************************************************************************
  2143. X/
  2144. X/ FUNCTION NAME: interrupt()
  2145. X/
  2146. X/ FUNCTION: handle interrupt from operator
  2147. X/
  2148. X/ AUTHOR: E. A. Estes, 12/4/85
  2149. X/
  2150. X/ ARGUMENTS: none
  2151. X/
  2152. X/ RETURN VALUE: none
  2153. X/
  2154. X/ MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(), 
  2155. X/    getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(), 
  2156. X/    crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(), 
  2157. X/    getanswer()
  2158. X/
  2159. X/ GLOBAL INPUTS: Player, *stdscr
  2160. X/
  2161. X/ GLOBAL OUTPUTS: none
  2162. X/
  2163. X/ DESCRIPTION:
  2164. X/    Allow player to quit upon hitting the interrupt key.
  2165. X/    If the player wants to quit while in battle, he/she automatically
  2166. X/    dies.
  2167. X/    If SHELL is defined, spawn a shell if the if the question is
  2168. X/    answered with a '!'.
  2169. X/    We are careful to save the state of the screen, and return it
  2170. X/    to its original condition.
  2171. X/
  2172. X/************************************************************************/
  2173. X
  2174. Xinterrupt()
  2175. X{
  2176. Xchar    line[81];        /* a place to store data already on screen */
  2177. Xregister int    loop;        /* counter */
  2178. Xint    x, y;            /* coordinates on screen */
  2179. Xint    ch;            /* input */
  2180. Xunsigned    savealarm;    /* to save alarm value */
  2181. X#ifdef SHELL
  2182. Xregister char    *shell;        /* pointer to shell to spawn */
  2183. Xint    childpid;        /* pid of spawned process */
  2184. X#endif
  2185. X
  2186. X#ifdef SYS3
  2187. X    signal(SIGINT, SIG_IGN);
  2188. X#endif
  2189. X#ifdef SYS5
  2190. X    signal(SIGINT, SIG_IGN);
  2191. X#endif
  2192. X
  2193. X    savealarm = alarm(0);        /* turn off any alarms */
  2194. X
  2195. X    getyx(stdscr, y, x);        /* save cursor location */
  2196. X
  2197. X    for (loop = 0; loop < 80; ++loop)    /* save line on screen */
  2198. X    {
  2199. X    move(4, loop);
  2200. X    line[loop] = inch();
  2201. X    }
  2202. X    line[80] = '\0';            /* nul terminate */
  2203. X
  2204. X    if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
  2205. X    /* in midst of fighting */
  2206. X    {
  2207. X    mvaddstr(4, 0, "Quitting now will automatically kill your character.  Still want to ? ");
  2208. X#ifdef SHELL
  2209. X    ch = getanswer("NY!", FALSE);
  2210. X#else
  2211. X    ch = getanswer("NY", FALSE);
  2212. X#endif
  2213. X    if (ch == 'Y')
  2214. X        death("Bailing out");
  2215. X        /*NOTREACHED*/
  2216. X    }
  2217. X    else
  2218. X    {
  2219. X#ifdef SHELL
  2220. X    mvaddstr(4, 0, "Do you really want to quit [! = Shell] ? ");
  2221. X    ch = getanswer("NY!", FALSE);
  2222. X#else
  2223. X    mvaddstr(4, 0, "Do you really want to quit ? ");
  2224. X    ch = getanswer("NY", FALSE);
  2225. X#endif
  2226. X    if (ch == 'Y')
  2227. X        leavegame();
  2228. X        /*NOTREACHED*/
  2229. X    }
  2230. X
  2231. X#ifdef SHELL
  2232. X    if (ch == '!')
  2233. X    /* shell escape */
  2234. X    {
  2235. X    if ((shell = getenv("SHELL")) == NULL)
  2236. X        /* use default */
  2237. X        shell = SHELL;
  2238. X
  2239. X    if ((childpid = fork()) == 0)
  2240. X        /* in child */
  2241. X        {
  2242. X        clear();
  2243. X        refresh();
  2244. X        cleanup(FALSE);        /* out of curses, close files */
  2245. X
  2246. X        setuid(getuid());        /* make sure we are running with real uid */
  2247. X        setgid(getgid());        /* make sure we are running with real gid */
  2248. X        execl(shell, shell, "-i", 0);
  2249. X        execl(SHELL, SHELL, "-i", 0);    /* last resort */
  2250. X
  2251. X        exit(0);
  2252. X        /*NOTREACHED*/
  2253. X        }
  2254. X    else
  2255. X        /* in parent */
  2256. X        {
  2257. X        while (wait((int *) NULL) != childpid);    /* wait until done */
  2258. X        crmode();            /* restore keyboard */
  2259. X        clearok(stdscr, TRUE);    /* force redraw of screen */
  2260. X        }
  2261. X    }
  2262. X#endif
  2263. X
  2264. X    mvaddstr(4, 0, line);         /* restore data on screen */
  2265. X    move(y, x);                /* restore cursor */
  2266. X    refresh();
  2267. X
  2268. X#ifdef SYS3
  2269. X    signal(SIGINT, interrupt);
  2270. X#endif
  2271. X#ifdef SYS5
  2272. X    signal(SIGINT, interrupt);
  2273. X#endif
  2274. X
  2275. X    alarm(savealarm);            /* restore alarm */
  2276. X}
  2277. X/* */
  2278. X/************************************************************************
  2279. X/
  2280. X/ FUNCTION NAME: getanswer()
  2281. X/
  2282. X/ FUNCTION: get an answer from operator
  2283. X/
  2284. X/ AUTHOR: E. A. Estes, 12/4/85
  2285. X/
  2286. X/ ARGUMENTS:
  2287. X/    char *choices - string of (upper case) valid choices
  2288. X/    bool def - set if default answer
  2289. X/
  2290. X/ RETURN VALUE: none
  2291. X/
  2292. X/ MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(), 
  2293. X/    _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
  2294. X/
  2295. X/ GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout, 
  2296. X/    Timeoenv[]
  2297. X/
  2298. X/ GLOBAL OUTPUTS: _iob[]
  2299. X/
  2300. X/ DESCRIPTION:
  2301. X/    Get a single character answer from operator.
  2302. X/    Timeout waiting for response.  If we timeout, or the
  2303. X/    answer in not in the list of valid choices, print choices,
  2304. X/    and wait again, otherwise return the first character in ths
  2305. X/    list of choices.
  2306. X/    Give up after 3 tries.
  2307. X/
  2308. X/************************************************************************/
  2309. X
  2310. Xgetanswer(choices, def)
  2311. Xchar    *choices;
  2312. Xbool    def;
  2313. X{
  2314. Xint    ch;            /* input */
  2315. Xint    loop;            /* counter */
  2316. Xint    oldx, oldy;        /* original coordinates on screen */
  2317. X
  2318. X    getyx(stdscr, oldy, oldx);
  2319. X    alarm(0);                /* make sure alarm is off */
  2320. X
  2321. X    for (loop = 3; loop; --loop)
  2322. X    /* try for 3 times */
  2323. X    {
  2324. X    if (setjmp(Timeoenv) != 0)
  2325. X        /* timed out waiting for response */
  2326. X        {
  2327. X        if (def || loop <= 1)
  2328. X        /* return default answer */
  2329. X        break;
  2330. X        else
  2331. X        /* prompt, and try again */
  2332. X        goto YELL;
  2333. X        }
  2334. X    else
  2335. X        /* wait for response */
  2336. X        {
  2337. X        clrtoeol();
  2338. X        refresh();
  2339. X#ifdef BSD41
  2340. X        sigset(SIGALRM, catchalarm);
  2341. X#else
  2342. X        signal(SIGALRM, catchalarm);
  2343. X#endif
  2344. X        /* set timeout */
  2345. X        if (Timeout)
  2346. X        alarm(7);        /* short */
  2347. X        else
  2348. X        alarm(600);        /* long */
  2349. X
  2350. X        ch = getchar();
  2351. X
  2352. X        alarm(0);            /* turn off timeout */
  2353. X
  2354. X        if (ch < 0)
  2355. X        /* caught some signal */
  2356. X        {
  2357. X        ++loop;
  2358. X        continue;
  2359. X        }
  2360. X        else if (ch == CH_REDRAW)
  2361. X        /* redraw screen */
  2362. X        {
  2363. X        clearok(stdscr, TRUE);    /* force clear screen */
  2364. X        ++loop;            /* don't count this input */
  2365. X        continue;
  2366. X        }
  2367. X        else if (Echo)
  2368. X        {
  2369. X        addch(ch);        /* echo character */
  2370. X        refresh();
  2371. X        }
  2372. X
  2373. X        if (islower(ch))
  2374. X        /* convert to upper case */
  2375. X        ch = toupper(ch);
  2376. X
  2377. X        if (def || strchr(choices, ch) != NULL)
  2378. X        /* valid choice */
  2379. X        return(ch);
  2380. X        else if (!def && loop > 1)
  2381. X        /* bad choice; prompt, and try again */
  2382. X        {
  2383. XYELL:        mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
  2384. X        move(oldy, oldx);
  2385. X        clrtoeol();
  2386. X        continue;
  2387. X        }
  2388. X        else
  2389. X        /* return default answer */
  2390. X        break;
  2391. X        }
  2392. X    }
  2393. X
  2394. X    return(*choices);
  2395. X}
  2396. X/* */
  2397. X/************************************************************************
  2398. X/
  2399. X/ FUNCTION NAME: catchalarm()
  2400. X/
  2401. X/ FUNCTION: catch timer when waiting for input
  2402. X/
  2403. X/ AUTHOR: E. A. Estes, 12/4/85
  2404. X/
  2405. X/ ARGUMENTS: none
  2406. X/
  2407. X/ RETURN VALUE: none
  2408. X/
  2409. X/ MODULES CALLED: longjmp()
  2410. X/
  2411. X/ GLOBAL INPUTS: Timeoenv[]
  2412. X/
  2413. X/ GLOBAL OUTPUTS: none
  2414. X/
  2415. X/ DESCRIPTION:
  2416. X/    Come here when the alarm expires while waiting for input.
  2417. X/    Simply longjmp() into getanswer().
  2418. X/
  2419. X/************************************************************************/
  2420. X
  2421. Xcatchalarm()
  2422. X{
  2423. X    longjmp(Timeoenv, 1);
  2424. X}
  2425. !EOR!
  2426.  
  2427.  
  2428.